今天來講Query Notion Database
一樣先上spec
/notion/queryNotionDatabase/{databaseId}:
post:
summary: Query data from a Notion database
parameters:
- name: databaseId
in: path
required: true
description: ID of the Notion database to query
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
filter:
type: object
description: JSON object defining query filters
sorts:
type: array
items:
type: string
responses:
'200':
description: Query results from Notion database
'400':
description: Invalid input
今天修改的部分和昨天差不多,所以主要上code就不會解釋太多
// QueryNotionDatabase godoc
//
// @Summary Query Notion Database
// @Description Queries a database, returning a paginated array of `Page` objects within the database.
// @Tags notion
// @Accept json
// @Produce json
// @Param databaseId path string true "Database ID"
// @Param request body requestModel.NotionQueryDatabaseRequest true "Request Body"
// @Success 200 {array} responseModel.NotionQueryDatabaseResponse
// @Failure 400 {string} string "Invalid input"
// @Router /api/v1/notion/queryDatabase/{databaseId} [post]
func (c *Controller) QueryNotionDatabase(ctx *gin.Context) {
// Get Authorization from config
configHandler := util.NewConfigHandler()
auth := configHandler.GetSecretConfig().Get("Authorization")
databaseId := ctx.Param("databaseId")
var requests requestModel.NotionQueryDatabaseRequest
if err := ctx.ShouldBindJSON(&requests); err != nil {
ctx.JSON(400, gin.H{"error": err.Error()})
return
}
// Marshal the struct to json
requestJson, err := json.Marshal(requests)
if err != nil {
log.Fatalln(err)
}
// Send the request to Notion API
client := handler.NewClient()
header := map[string]string{
"Authorization": auth.(string),
"Notion-Version": "2022-06-28",
"Content-Type": "application/json",
}
body := []byte(requestJson)
response, err := client.Post("https://api.notion.com/v1/databases/"+databaseId+"/query", header, body)
if err != nil {
log.Fatalln(err)
}
defer response.Body.Close()
// Change the response body to []byte type
responseBody, err := io.ReadAll(response.Body)
if err != nil {
log.Fatalln(err)
}
bodyStr := string(responseBody)
var data []byte = []byte(bodyStr)
// Unmarshal the response body to struct
var responseQueryNotionDatabase responseModel.NotionQueryDatabaseResponse
json.Unmarshal(data, &responseQueryNotionDatabase)
ctx.JSON(http.StatusOK, responseQueryNotionDatabase)
}
controller的地方主要就是修改swaggo,controller的地方跟昨天很像
唯一不同的部分為昨天是把request的內容轉成string塞進去[]byte
今天則是直接轉這個資料型態
type NotionQueryDatabaseRequest struct {
Sorts []map[string]interface{} `json:"sorts"`
Filter map[string]interface{} `json:"filter"`
}
這邊就是加上sorts跟filter的部分
type Database struct {
Object string `json:"object"`
ID string `json:"id"`
CreatedTime string `json:"created_time"`
LastEditedTime string `json:"last_edited_time"`
CreatedBy struct {
Object string `json:"object"`
ID string `json:"id"`
} `json:"created_by"`
LastEditedBy struct {
Object string `json:"object"`
ID string `json:"id"`
} `json:"last_edited_by"`
Cover interface{} `json:"cover"`
Icon interface{} `json:"icon"`
Parent struct {
Type string `json:"type"`
DatabaseID string `json:"database_id"`
} `json:"parent"`
Archived bool `json:"archived"`
Properties map[string]interface{} `json:"properties"`
URL string `json:"url"`
PublicURL interface{} `json:"public_url"`
}
type NotionQueryDatabaseResponse struct {
Object string `json:"object"`
Results []Database `json:"results"`
NextCursor interface{} `json:"next_cursor"`
HasMore bool `json:"has_more"`
Type string `json:"type"`
PageOrDB struct{} `json:"page_or_database"`
DeveloperSurvey string `json:"developer_survey"`
}
這邊的內容也主要是從官方文件來的
Start building with the Notion API
再利用chatGPT轉成golang的型態
func main() {
r := gin.Default()
c := controller.NewController()
v1 := r.Group("/api/v1")
{
notion := v1.Group("/notion")
{
notion.POST("/createDatabase/:pageId", c.CreateNotionDatabase)
notion.POST("/queryDatabase/:databaseId", c.QueryNotionDatabase)
}
...
這邊主要就是多加一個路徑上去
大概有新增的部分就是這些
接下來做個小小的demo
{
"filter": {
"and": [
{
"property": "Date",
"date": {
"on_or_after": "2023-10-08T00:00:00+08:00"
}
},
{
"property": "Date",
"date": {
"before": "2023-10-09T00:00:00+08:00"
}
}
]
},
"sorts": [
]
}
在DB中加上以上資料
{
"object": "list",
"results": [
{
"object": "page",
"id": "62a2da36-0f63-4438-a177-3481b6d8019f",
"created_time": "2023-10-08T08:06:00.000Z",
"last_edited_time": "2023-10-08T08:07:00.000Z",
"created_by": {
"object": "user",
"id": "a57b5d4d-5914-46e7-9dc0-f964bbaf7289"
},
"last_edited_by": {
"object": "user",
"id": "a57b5d4d-5914-46e7-9dc0-f964bbaf7289"
},
"cover": null,
"icon": null,
"parent": {
"type": "database_id",
"database_id": "937094e2-c60c-499b-ba07-933a77baec7d"
},
"archived": false,
"properties": {
"Date": {
"date": {
"end": "2023-10-08T12:00:00.000+08:00",
"start": "2023-10-08T09:00:00.000+08:00",
"time_zone": null
},
"id": "s%7D%5CP",
"type": "date"
},
"Title": {
"id": "title",
"title": [
{
"annotations": {
"bold": false,
"code": false,
"color": "default",
"italic": false,
"strikethrough": false,
"underline": false
},
"href": null,
"plain_text": "Work",
"text": {
"content": "Work",
"link": null
},
"type": "text"
}
],
"type": "title"
}
},
"url": "https://www.notion.so/Work-62a2da360f634438a1773481b6d8019f",
"public_url": null
},
{
"object": "page",
"id": "e76378ae-0066-4cfe-883b-a8ede10bf1bf",
"created_time": "2023-10-08T08:06:00.000Z",
"last_edited_time": "2023-10-08T08:06:00.000Z",
"created_by": {
"object": "user",
"id": "a57b5d4d-5914-46e7-9dc0-f964bbaf7289"
},
"last_edited_by": {
"object": "user",
"id": "a57b5d4d-5914-46e7-9dc0-f964bbaf7289"
},
"cover": null,
"icon": null,
"parent": {
"type": "database_id",
"database_id": "937094e2-c60c-499b-ba07-933a77baec7d"
},
"archived": false,
"properties": {
"Date": {
"date": {
"end": "2023-10-08T09:00:00.000+08:00",
"start": "2023-10-08T07:00:00.000+08:00",
"time_zone": null
},
"id": "s%7D%5CP",
"type": "date"
},
"Title": {
"id": "title",
"title": [
{
"annotations": {
"bold": false,
"code": false,
"color": "default",
"italic": false,
"strikethrough": false,
"underline": false
},
"href": null,
"plain_text": "GYM",
"text": {
"content": "GYM",
"link": null
},
"type": "text"
}
],
"type": "title"
}
},
"url": "https://www.notion.so/GYM-e76378ae00664cfe883ba8ede10bf1bf",
"public_url": null
},
{
"object": "page",
"id": "008ab7be-1a19-4dd8-a425-38f1199f14e0",
"created_time": "2023-10-08T08:05:00.000Z",
"last_edited_time": "2023-10-08T08:06:00.000Z",
"created_by": {
"object": "user",
"id": "a57b5d4d-5914-46e7-9dc0-f964bbaf7289"
},
"last_edited_by": {
"object": "user",
"id": "a57b5d4d-5914-46e7-9dc0-f964bbaf7289"
},
"cover": null,
"icon": null,
"parent": {
"type": "database_id",
"database_id": "937094e2-c60c-499b-ba07-933a77baec7d"
},
"archived": false,
"properties": {
"Date": {
"date": {
"end": "2023-10-08T07:00:00.000+08:00",
"start": "2023-10-08T06:00:00.000+08:00",
"time_zone": null
},
"id": "s%7D%5CP",
"type": "date"
},
"Title": {
"id": "title",
"title": [
{
"annotations": {
"bold": false,
"code": false,
"color": "default",
"italic": false,
"strikethrough": false,
"underline": false
},
"href": null,
"plain_text": "commute",
"text": {
"content": "commute",
"link": null
},
"type": "text"
}
],
"type": "title"
}
},
"url": "https://www.notion.so/commute-008ab7be1a194dd8a42538f1199f14e0",
"public_url": null
}
],
"next_cursor": null,
"has_more": false,
"type": "page_or_database",
"page_or_database": {},
"developer_survey": ""
}
可以看到有拿到時間跟content,所以query的部分也完成了